package com.learn.fabric.app.demo.controller;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com.learn.fabric.app.demo.config.HyperLedgerFabricProperties;
import com.learn.fabric.app.demo.dto.CatDTO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.codec.binary.StringUtils;


import org.hyperledger.fabric.gateway.*;
import org.hyperledger.fabric.sdk.ChaincodeEventListener;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.json.Json;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.function.Consumer;

@RestController
@RequestMapping("/cat")
@Slf4j
@AllArgsConstructor
public class CatContractController {

    final Gateway gateway;

    final Network network;

    private static Contract catContract;



    final HyperLedgerFabricProperties hyperLedgerFabricProperties;

    @PostConstruct
    public void init()
    {
        catContract = network.getContract("hyperledger-fabric-contract-java-demo-learnCat","CatContract");
//        ChaincodeEventListener listener = new MychaincodeEventListen();
        //增加监听器
        catContract.addContractListener(new Consumer<ContractEvent>() {
            @Override
            public void accept(ContractEvent contractEvent) {
                log.info("=================="+contractEvent.getName());
                Optional<byte[]> payload = contractEvent.getPayload();
                byte[] payload_bytes = payload.get();
                log.info("==========================="+StringUtils.newStringUtf8(payload_bytes));
            }
        });

        log.info("catContract初始化成功！");
    }

    /**
     * description: 根据key查询
     * @param key
     * @return
     * @throws GatewayException
     */
    @GetMapping("/{key}")
    public Map<String, Object> queryCatByKey(@PathVariable String key) throws GatewayException {

        Map<String, Object> result = Maps.newConcurrentMap();
        byte[] cat = catContract.evaluateTransaction("queryCat", key);

        result.put("payload", StringUtils.newStringUtf8(cat));
        result.put("status", "ok");

        return result;
    }

    /**
     * description：新增cat
     * @param cat
     * @return
     * @throws Exception
     */
    @PutMapping("/")
    public Map<String, Object> createCat(@RequestBody CatDTO cat) throws Exception {

        Map<String, Object> result = Maps.newConcurrentMap();


        byte[] bytes = catContract.submitTransaction("createCat", cat.getKey(), cat.getName(), String.valueOf(cat.getAge()), cat.getColor(), cat.getBreed());

        result.put("payload", StringUtils.newStringUtf8(bytes));
        result.put("status", "ok");
        return result;
    }



    /**
     * description: 更新cat
     * @param cat
     * @return
     * @throws Exception
     */
    @PostMapping("/")
    public Map<String, Object> updateCat(@RequestBody CatDTO cat) throws Exception {

        Map<String, Object> result = Maps.newConcurrentMap();
        byte[] bytes = catContract.submitTransaction("updateCat", cat.getKey(), cat.getName(), String.valueOf(cat.getAge()), cat.getColor(), cat.getBreed());

        result.put("payload", StringUtils.newStringUtf8(bytes));
        result.put("status", "ok");

        return result;
    }

    /**
     * description: 根据key删除cat
     * @param key
     * @return
     * @throws Exception
     */
    @DeleteMapping("/{key}")
    public Map<String, Object> deleteCatByKey(@PathVariable String key) throws Exception {

        Map<String, Object> result = Maps.newConcurrentMap();

        byte[] cat = catContract.submitTransaction("deleteCat" , key);

        result.put("payload", StringUtils.newStringUtf8(cat));
        result.put("status", "ok");

        return result;
    }

    @GetMapping("/queryAll")
    public Map<String,Object> queryAll() throws ContractException {
        Map<String, Object> result = Maps.newConcurrentMap();
        byte[] cats = catContract.evaluateTransaction("queryAll");

        result.put("payload", StringUtils.newStringUtf8(cats));
        result.put("status", "ok");
        return   result;
    }

}
